Live from New York it's Saturday Night

Saturday Night Live Interactive Collaboration Dashboard

By Tali Zacks

How often have you been watching an Adam Sandler movie, sitting there thinking "David Spade and Rob Schneider... AGAIN?" Or perhaps you're enjoying the comedic works of Fred Armisen, when you notice Maya Rudolph and Andy Samberg keep popping up. Of course you can't think of Amy Poehler without her partner in crime, Tina Fey, also coming to mind.
If your go to genre is comedy, then you've likely noticed that when a project features an SNL cast member, there is a good chance two or more other SNL players are involves as well. But how frequently do these collaborations occur? Well we can start by taking a look at the complete list of SNL players, the time they spent on the show, and how that time overlaps.

The below graphic is from a wikipedia article: List of Saturday Night Live cast members
Lighter colors denote repertory cast members versus "featured players".

Timeline

Once you've taken a look at the full cast, you can appreciate the overlap in time spent on the show and maybe understand the strength of relationships built between cast members who spent 5+ seasons together, rehearsing every weekday and preforming every saturday night for half of the calendar year.

To begin, lets take a look at the overlap between (non-SNL-related) projects. I began by analyzing the crossover between IMDb 'knownForTitles,' the set of four or five titles on the cover page of an actor's IMDb page. I created the following graphic by doing just that. I first ensured that for every entry of an SNL actor's name in the IMDb dataset, I was appending the knownForTitles to a larger list of titles for that actor and also a complete list of knownForTitles for all the actors. That process involved creating a boolean table which checked for each title against an actor's knownForTitles list.

Full Heat Map

Following the creation of the IMDb, full heat map (including 159 cast members and a fraction of the 1127 knownForTitles), I was able to start creating boolean tables that determined cell values based on the existence of a selected actor's knownForTitles amongst the knownForTitles lists of the other 158 actors. Each table is then called to create a binary heat map based on a call from the bqplot barchart bar selection. The final dashboard is displayed at the end of the article.

I wanted to create more accurate comprehensive lists of projects that each cast member has been involved in. I did this through a process called web scraping. I scraped wikipedia 'Filmography' tables for each SNL cast member. The table in the List of Saturday Night Live cast members Wikipedia page became a perfect hub of the SNL players' Wikipedia hyperlinks. I used those links and the Filmography tables on each page to build the lists of each actor's tv and film projects.
Below, I have included Maya Rudolph's tv project list. It was combined with her film list and then assigned to her dictionary key as a value list.
This dictionary replaced the knownForTitles and the boolean tables were recreated based on the new dictionary.

In [36]:
"hide-output"hide-output
In [37]:
Out[37]:
['Chicago Hope',
 "The Devil's Child",
 'Action',
 'City of Angels',
 'Saturday Night Live',
 'Campus Ladies',
 'The Simpsons',
 'Kath & Kim',
 'The Mighty B!',
 'Up All Night',
 'Saturday Night Live',
 'Portlandia',
 'The Maya Rudolph Show',
 'Family Guy',
 'The Awesomes',
 'Comedy Bang! Bang!',
 'The Spoils Before Dying',
 'Drunk History',
 'Angie Tribeca',
 'Maya & Marty',
 'Brooklyn Nine-Nine',
 'Documentary Now!',
 'The Grinder',
 'Mike Tyson Mysteries',
 "Michael Bolton's Big, Sexy Valentine's Day Special",
 'Nobodies',
 'Unbreakable Kimmy Schmidt',
 'Tour de Pharmacy',
 'The Gong Show',
 'Big Mouth',
 'Big Hero 6: The Series',
 'A Christmas Story Live!',
 'The Good Place',
 'Forever',
 'I Love You, America with Sarah Silverman',
 'The Unauthorized Bash Brothers Experience',
 'Nailed It!',
 'Bless the Harts',
 'Mapleworth Murders',
 "Eater's Guide to the World",
 "Sarah Cooper: Everything's Fine",
 'Baking It',
 'A Clüsterfünke Christmas',
 'MacGruber',
 'Human Resources',
 'Loot']

To use the dashboard below, click on an actor's bar in the barchart on the left hand side of the screen. The label on top displays the number of seasons that actor was on SNL. When an actor's bar is selected, the binary heat map on the right hand side of the dashboard is also updated. Each column represents a different project that the selected actor was incolved in and each row represents an SNL cast member. If a box is light blue, it means that row's actor contributed to that column's project. If you use your mouse to hover over any box, a tooltip will display the row's actor, the column's project, and either a 1 or a 0 (1 -> involved, 0 -> not involved).

Note: On occasion, if an actor is chosen and their projects only include SNL, the heatmap gets a tad glitchy and it might swap the color scale. To correct this, re-run the following cell

In [39]:
Kenan Thompson: 19 seasons on SNL
Alan ZweibelSasheer ZamataBowen YangFred WolfCasey WilsonKristen WiigBrooks WheelanNoël WellsPatrick WeathersDamon WayansMichaela WatkinsNancy WallsDan VitaleMelissa VillaseñorDanitra VanceKenan ThompsonTerry SweeneyJulia SweeneyJason SudeikisCecily StrongBen StillerPamela StephensonDavid SpadeRobert SmigelJenny SlateSarah SilvermanMartin ShortSarah ShermanHarry ShearerMolly ShannonPaul ShafferRob SchneiderTom SchillerHoratio SanzAdam SandlerAndy SambergMaya RudolphJon RudnitskyTony RosatoCharles RocketChris RockTim RobinsonAnn RisleyRob RiggleJeff RichardsChris ReddGilda RadnerColin QuinnRandy QuaidEmily PragerAmy PoehlerJoe PiscopoJay PharoahNasim PedradChris ParnellCheri OteriMichael O'DonoghueMike O'BrienEgo NwodimLuke NullDon NovelloLaraine NewmanKevin NealonMike MyersBill MurrayEddie MurphyBobby MoynihanGarrett MorrisTracy MorganKyle MooneyJay MohrAlex MoffatFinesse MitchellJerry MinorDennis MillerJohn MilhiserSeth MeyersLaurie MetcalfTim MeadowsKate McKinnonMark McKinneyMichael McKeanGail MatthiusNorm MacdonaldJon LovitzJulia Louis-DreyfusMatthew LauranceGary KroegerDavid KoechnerTaran KillamLaura KightlingerTim KazurinskyChris KattanColin JostLeslie JonesPunkie JohnsonJames Austin JohnsonVictoria JacksonMelanie HutsellYvonne HudsonJan HooksLauren HoltPhil HartmanDarrell HammondRich HallBrad HallAnthony Michael HallBill HaderChristopher GuestMary GrossGilbert GottfriedAna GasteyerJaneane GarofaloHeidi GardnerAl FrankenWill ForteChloe FinemanTina FeyWill FerrellChris FarleySiobhan FallonJimmy FallonChris ElliottAbby ElliottDean EdwardsChristine EbersoleNora DunnRobin DukeRachel DratchBrian Doyle-MurrayRobert Downey Jr.Jim DowneyAndrew DismukesDenny DillonMikey DayTom DavisPete DavidsonJoan CusackJane CurtinBilly CrystalGeorge CoeEllen CleghorneMichael CheChevy ChaseDana CarveyBeth CahillAidy BryantA. Whitney BrownPaul BrittainJim BreuerBeck BennettJohn BelushiJim BelushiVanessa BayerMorwenna BanksPeter AykroydDan AykroydAristotle AthariFred ArmisenSNL Cast Member024681012141618Number of Seasons on SNL
ProjectsActorsColor Scale01
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
~/.conda/envs/DataViz2/lib/python3.7/site-packages/ipywidgets/widgets/widget.py in _handle_msg(self, msg)
    674                 if 'buffer_paths' in data:
    675                     _put_buffers(state, data['buffer_paths'], msg['buffers'])
--> 676                 self.set_state(state)
    677 
    678         # Handle a state request.

~/.conda/envs/DataViz2/lib/python3.7/site-packages/ipywidgets/widgets/widget.py in set_state(self, sync_data)
    543                     from_json = self.trait_metadata(name, 'from_json',
    544                                                     self._trait_from_json)
--> 545                     self.set_trait(name, from_json(sync_data[name], self))
    546 
    547     def send(self, content, buffers=None):

~/.conda/envs/DataViz2/lib/python3.7/contextlib.py in __exit__(self, type, value, traceback)
    117         if type is None:
    118             try:
--> 119                 next(self.gen)
    120             except StopIteration:
    121                 return False

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in hold_trait_notifications(self)
   1214         Parameters
   1215         ----------
-> 1216         handler : callable, None
   1217             A callable that is called when a trait changes.  Its
   1218             signature can be handler(), handler(name), handler(name, new),

~/.conda/envs/DataViz2/lib/python3.7/site-packages/ipywidgets/widgets/widget.py in notify_change(self, change)
    604                 # Send new state to front-end
    605                 self.send_state(key=name)
--> 606         super(Widget, self).notify_change(change)
    607 
    608     def __repr__(self):

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in notify_change(self, change)
   1227         """
   1228         warn("on_trait_change is deprecated in traitlets 4.1: use observe instead",
-> 1229              DeprecationWarning, stacklevel=2)
   1230         if name is None:
   1231             name = All

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in _notify_observers(self, event)
   1264         for n in names:
   1265             self._add_notifiers(handler, n, type)
-> 1266 
   1267     def unobserve(self, handler, names=All, type='change'):
   1268         """Remove a trait change handler.

~/Desktop/GradSchool/Spring22/SNL_Final/SNL_Final.py in on_selection(change)
    251             heat_map.color = table.values.astype('float')
    252             heat_map.row = table.index.values.astype(str),
--> 253             heat_map.column = table.columns.values.astype(str)
    254 
    255 

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in __set__(self, obj, value)
    604                 "use @validate decorator instead.")
    605             value = cross_validate(value, self)
--> 606         return value
    607 
    608     def __or__(self, other):

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traittypes/traittypes.py in set(self, obj, value)
    106 
    107     def set(self, obj, value):
--> 108         new_value = self._validate(obj, value)
    109         old_value = obj._trait_values.get(self.name, self.default_value)
    110         obj._trait_values[self.name] = new_value

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in _validate(self, obj, value)
    612             return Union([self, other])
    613 
--> 614     def info(self):
    615         return self.info_text
    616 

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in _cross_validate(self, obj, value)
    618         if obj is not None:
    619             e = "The '%s' trait of %s instance must be %s, but a value of %s was specified." \
--> 620                 % (self.name, class_of(obj),
    621                    self.info(), repr_type(value))
    622         else:

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in __call__(self, *args, **kwargs)
    975             else:
    976                 if isinstance(value, BaseDescriptor):
--> 977                     value.instance_init(self)
    978 
    979 

~/.conda/envs/DataViz2/lib/python3.7/site-packages/bqplot/marks.py in _validate_column(self, proposal)
   1604 
   1605         color = np.asarray(self.color)
-> 1606         n_columns = color.shape[1]
   1607         if len(column) != n_columns and len(column) != n_columns + 1 and len(column) != n_columns - 1:
   1608             raise TraitError('column must be an array of size color.shape[1]')

IndexError: tuple index out of range

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
~/.conda/envs/DataViz2/lib/python3.7/site-packages/ipywidgets/widgets/widget.py in _handle_msg(self, msg)
    674                 if 'buffer_paths' in data:
    675                     _put_buffers(state, data['buffer_paths'], msg['buffers'])
--> 676                 self.set_state(state)
    677 
    678         # Handle a state request.

~/.conda/envs/DataViz2/lib/python3.7/site-packages/ipywidgets/widgets/widget.py in set_state(self, sync_data)
    543                     from_json = self.trait_metadata(name, 'from_json',
    544                                                     self._trait_from_json)
--> 545                     self.set_trait(name, from_json(sync_data[name], self))
    546 
    547     def send(self, content, buffers=None):

~/.conda/envs/DataViz2/lib/python3.7/contextlib.py in __exit__(self, type, value, traceback)
    117         if type is None:
    118             try:
--> 119                 next(self.gen)
    120             except StopIteration:
    121                 return False

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in hold_trait_notifications(self)
   1214         Parameters
   1215         ----------
-> 1216         handler : callable, None
   1217             A callable that is called when a trait changes.  Its
   1218             signature can be handler(), handler(name), handler(name, new),

~/.conda/envs/DataViz2/lib/python3.7/site-packages/ipywidgets/widgets/widget.py in notify_change(self, change)
    604                 # Send new state to front-end
    605                 self.send_state(key=name)
--> 606         super(Widget, self).notify_change(change)
    607 
    608     def __repr__(self):

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in notify_change(self, change)
   1227         """
   1228         warn("on_trait_change is deprecated in traitlets 4.1: use observe instead",
-> 1229              DeprecationWarning, stacklevel=2)
   1230         if name is None:
   1231             name = All

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in _notify_observers(self, event)
   1264         for n in names:
   1265             self._add_notifiers(handler, n, type)
-> 1266 
   1267     def unobserve(self, handler, names=All, type='change'):
   1268         """Remove a trait change handler.

~/Desktop/GradSchool/Spring22/SNL_Final/SNL_Final.py in on_selection(change)
    251             heat_map.color = table.values.astype('float')
    252             heat_map.row = table.index.values.astype(str),
--> 253             heat_map.column = table.columns.values.astype(str)
    254 
    255 

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in __set__(self, obj, value)
    604                 "use @validate decorator instead.")
    605             value = cross_validate(value, self)
--> 606         return value
    607 
    608     def __or__(self, other):

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traittypes/traittypes.py in set(self, obj, value)
    106 
    107     def set(self, obj, value):
--> 108         new_value = self._validate(obj, value)
    109         old_value = obj._trait_values.get(self.name, self.default_value)
    110         obj._trait_values[self.name] = new_value

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in _validate(self, obj, value)
    612             return Union([self, other])
    613 
--> 614     def info(self):
    615         return self.info_text
    616 

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in _cross_validate(self, obj, value)
    618         if obj is not None:
    619             e = "The '%s' trait of %s instance must be %s, but a value of %s was specified." \
--> 620                 % (self.name, class_of(obj),
    621                    self.info(), repr_type(value))
    622         else:

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in __call__(self, *args, **kwargs)
    975             else:
    976                 if isinstance(value, BaseDescriptor):
--> 977                     value.instance_init(self)
    978 
    979 

~/.conda/envs/DataViz2/lib/python3.7/site-packages/bqplot/marks.py in _validate_column(self, proposal)
   1604 
   1605         color = np.asarray(self.color)
-> 1606         n_columns = color.shape[1]
   1607         if len(column) != n_columns and len(column) != n_columns + 1 and len(column) != n_columns - 1:
   1608             raise TraitError('column must be an array of size color.shape[1]')

IndexError: tuple index out of range

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
~/.conda/envs/DataViz2/lib/python3.7/site-packages/ipywidgets/widgets/widget.py in _handle_msg(self, msg)
    674                 if 'buffer_paths' in data:
    675                     _put_buffers(state, data['buffer_paths'], msg['buffers'])
--> 676                 self.set_state(state)
    677 
    678         # Handle a state request.

~/.conda/envs/DataViz2/lib/python3.7/site-packages/ipywidgets/widgets/widget.py in set_state(self, sync_data)
    543                     from_json = self.trait_metadata(name, 'from_json',
    544                                                     self._trait_from_json)
--> 545                     self.set_trait(name, from_json(sync_data[name], self))
    546 
    547     def send(self, content, buffers=None):

~/.conda/envs/DataViz2/lib/python3.7/contextlib.py in __exit__(self, type, value, traceback)
    117         if type is None:
    118             try:
--> 119                 next(self.gen)
    120             except StopIteration:
    121                 return False

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in hold_trait_notifications(self)
   1214         Parameters
   1215         ----------
-> 1216         handler : callable, None
   1217             A callable that is called when a trait changes.  Its
   1218             signature can be handler(), handler(name), handler(name, new),

~/.conda/envs/DataViz2/lib/python3.7/site-packages/ipywidgets/widgets/widget.py in notify_change(self, change)
    604                 # Send new state to front-end
    605                 self.send_state(key=name)
--> 606         super(Widget, self).notify_change(change)
    607 
    608     def __repr__(self):

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in notify_change(self, change)
   1227         """
   1228         warn("on_trait_change is deprecated in traitlets 4.1: use observe instead",
-> 1229              DeprecationWarning, stacklevel=2)
   1230         if name is None:
   1231             name = All

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in _notify_observers(self, event)
   1264         for n in names:
   1265             self._add_notifiers(handler, n, type)
-> 1266 
   1267     def unobserve(self, handler, names=All, type='change'):
   1268         """Remove a trait change handler.

~/Desktop/GradSchool/Spring22/SNL_Final/SNL_Final.py in on_selection(change)
    251             heat_map.color = table.values.astype('float')
    252             heat_map.row = table.index.values.astype(str),
--> 253             heat_map.column = table.columns.values.astype(str)
    254 
    255 

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in __set__(self, obj, value)
    604                 "use @validate decorator instead.")
    605             value = cross_validate(value, self)
--> 606         return value
    607 
    608     def __or__(self, other):

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traittypes/traittypes.py in set(self, obj, value)
    106 
    107     def set(self, obj, value):
--> 108         new_value = self._validate(obj, value)
    109         old_value = obj._trait_values.get(self.name, self.default_value)
    110         obj._trait_values[self.name] = new_value

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in _validate(self, obj, value)
    612             return Union([self, other])
    613 
--> 614     def info(self):
    615         return self.info_text
    616 

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in _cross_validate(self, obj, value)
    618         if obj is not None:
    619             e = "The '%s' trait of %s instance must be %s, but a value of %s was specified." \
--> 620                 % (self.name, class_of(obj),
    621                    self.info(), repr_type(value))
    622         else:

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in __call__(self, *args, **kwargs)
    975             else:
    976                 if isinstance(value, BaseDescriptor):
--> 977                     value.instance_init(self)
    978 
    979 

~/.conda/envs/DataViz2/lib/python3.7/site-packages/bqplot/marks.py in _validate_column(self, proposal)
   1604 
   1605         color = np.asarray(self.color)
-> 1606         n_columns = color.shape[1]
   1607         if len(column) != n_columns and len(column) != n_columns + 1 and len(column) != n_columns - 1:
   1608             raise TraitError('column must be an array of size color.shape[1]')

IndexError: tuple index out of range

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
~/.conda/envs/DataViz2/lib/python3.7/site-packages/ipywidgets/widgets/widget.py in _handle_msg(self, msg)
    674                 if 'buffer_paths' in data:
    675                     _put_buffers(state, data['buffer_paths'], msg['buffers'])
--> 676                 self.set_state(state)
    677 
    678         # Handle a state request.

~/.conda/envs/DataViz2/lib/python3.7/site-packages/ipywidgets/widgets/widget.py in set_state(self, sync_data)
    543                     from_json = self.trait_metadata(name, 'from_json',
    544                                                     self._trait_from_json)
--> 545                     self.set_trait(name, from_json(sync_data[name], self))
    546 
    547     def send(self, content, buffers=None):

~/.conda/envs/DataViz2/lib/python3.7/contextlib.py in __exit__(self, type, value, traceback)
    117         if type is None:
    118             try:
--> 119                 next(self.gen)
    120             except StopIteration:
    121                 return False

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in hold_trait_notifications(self)
   1214         Parameters
   1215         ----------
-> 1216         handler : callable, None
   1217             A callable that is called when a trait changes.  Its
   1218             signature can be handler(), handler(name), handler(name, new),

~/.conda/envs/DataViz2/lib/python3.7/site-packages/ipywidgets/widgets/widget.py in notify_change(self, change)
    604                 # Send new state to front-end
    605                 self.send_state(key=name)
--> 606         super(Widget, self).notify_change(change)
    607 
    608     def __repr__(self):

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in notify_change(self, change)
   1227         """
   1228         warn("on_trait_change is deprecated in traitlets 4.1: use observe instead",
-> 1229              DeprecationWarning, stacklevel=2)
   1230         if name is None:
   1231             name = All

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in _notify_observers(self, event)
   1264         for n in names:
   1265             self._add_notifiers(handler, n, type)
-> 1266 
   1267     def unobserve(self, handler, names=All, type='change'):
   1268         """Remove a trait change handler.

~/Desktop/GradSchool/Spring22/SNL_Final/SNL_Final.py in on_selection(change)
    251             heat_map.color = table.values.astype('float')
    252             heat_map.row = table.index.values.astype(str),
--> 253             heat_map.column = table.columns.values.astype(str)
    254 
    255 

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in __set__(self, obj, value)
    604                 "use @validate decorator instead.")
    605             value = cross_validate(value, self)
--> 606         return value
    607 
    608     def __or__(self, other):

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traittypes/traittypes.py in set(self, obj, value)
    106 
    107     def set(self, obj, value):
--> 108         new_value = self._validate(obj, value)
    109         old_value = obj._trait_values.get(self.name, self.default_value)
    110         obj._trait_values[self.name] = new_value

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in _validate(self, obj, value)
    612             return Union([self, other])
    613 
--> 614     def info(self):
    615         return self.info_text
    616 

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in _cross_validate(self, obj, value)
    618         if obj is not None:
    619             e = "The '%s' trait of %s instance must be %s, but a value of %s was specified." \
--> 620                 % (self.name, class_of(obj),
    621                    self.info(), repr_type(value))
    622         else:

~/.conda/envs/DataViz2/lib/python3.7/site-packages/traitlets/traitlets.py in __call__(self, *args, **kwargs)
    975             else:
    976                 if isinstance(value, BaseDescriptor):
--> 977                     value.instance_init(self)
    978 
    979 

~/.conda/envs/DataViz2/lib/python3.7/site-packages/bqplot/marks.py in _validate_column(self, proposal)
   1604 
   1605         color = np.asarray(self.color)
-> 1606         n_columns = color.shape[1]
   1607         if len(column) != n_columns and len(column) != n_columns + 1 and len(column) != n_columns - 1:
   1608             raise TraitError('column must be an array of size color.shape[1]')

IndexError: tuple index out of range

In [ ]: